/*  
 *  Copyright 2006 Paul Jack.
 *
 *  This file is part of the Dex compiler suite. 
 *  
 *  Dex is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU General Public License as published by the
 *  Free Software Foundation; either version 2 of the License, or (at your
 *  option) any later version.
 *  
 *  Dex is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 *  Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 */
package dex.compiler.model.statement;


import dex.compiler.model.base.Place;
import dex.compiler.model.expression.Expression;
import dex.compiler.model.expression.Infix;


/**
 * An assignment statement, such as x = 42.
 * 
 * <p>An assignment consists of an lvalue, an rvalue and an optional
 * operator.  The rvalue determines the value being assigned; the
 * lvalue determines where that value is stored.
 * 
 * <p>An lvalue must be a {@link dex.compiler.model.expression.IdentifierExpression}
 * (like <code>x = 42</code>), a {@link dex.compiler.model.expression.ArrayExpression}
 * (like <code>x[i] = 42</code>), or a {@link dex.compiler.model.expression.MemberExpression} 
 * (like <code>foo.x = 42</code>).  This requirement is not checked until semantic
 * analysis, however; the parser will accept any expression as an lvalue.
 * 
 * <p>The optional operator allows for "shortcut assignments" like 
 * <code>x += 42</code>, which is equivalent to <code>x = x + 42</code>.
 * Comparison operators are not allowed as assignment operators, but 
 * again, this is not enforced until semantic analysis.
 */
public class Assignment extends Statement {
	
	
	/**
	 * The operator to use during assignment.  If null, then 
	 * just the normal assignment operator <code>=<code> is to be used.
	 */
	private Infix operator;
	
	
	/**
	 * The lvalue of the assignment.
	 */
	private Expression lvalue;
	
	
	/**
	 * The rvalue of the assignment
	 */
	private Expression rvalue;
	

	/**
	 * Constructs a new assignment statement.
	 * 
	 * @param place  the place where the statement originated
	 * @param operator  the operator to use during assignment; for normal
	 *   assignment, use null
	 * @param lvalue  the lvalue of the assignment
	 * @param rvalue  the rvalue of the assignment
	 */
	public Assignment(Place place, Infix operator, Expression lvalue, Expression rvalue) {
		super(place);
		if (lvalue == null) {
			throw new IllegalArgumentException();
		}
		if (rvalue == null) {
			throw new IllegalArgumentException();
		}
		this.operator = operator;
		this.lvalue = lvalue;
		this.rvalue = rvalue;
	}
		

	@Override
	public String toString() {
		String symbol = (operator == null) ? "" : operator.getSymbol();
		return lvalue + " " + symbol + "= " + rvalue;  
	}
	

	/**
	 * Returns the lvalue.
	 * 
	 * @return  the lvalue
	 */
	public Expression getLValue() {
		return lvalue;
	}
	
	
	/**
	 * Returns the rvalue.
	 * 
	 * @return the rvalue.
	 */
	public Expression getRValue() {
		return rvalue;
	}
	
	
	/**
	 * Returns the optional operator.
	 * 
	 * @return  the operator to use during assignment, or null to
	 *  just do a normal assignment
	 */
	public Infix getOperator() {
		return operator;
	}


	@Override
	public boolean terminates() {
		return false;
	}
	

}
